const { User, Invitation, PointsTransaction } = require('../models')
const ShareStatisticsService = require('./shareStatisticsService')
const InviteAntiCheatService = require('./inviteAntiCheatService')
const crypto = require('crypto')
const QRCode = require('qrcode')
const logger = require('../utils/logger')

class InvitationService {
  /**
   * 生成唯一邀请码
   * @param {number} userId - 用户ID
   * @returns {string} 邀请码
   */
  static generateInviteCode(userId) {
    // 使用用户ID和时间戳生成唯一码
    const timestamp = Date.now().toString(36)
    const userIdStr = userId.toString(36)
    const random = Math.random().toString(36).substring(2, 6)
    
    // 组合并取前8位
    const combined = `${userIdStr}${timestamp}${random}`
    return combined.substring(0, 8).toUpperCase()
  }

  /**
   * 获取用户邀请码
   * @param {number} userId - 用户ID
   * @returns {Promise<string>} 邀请码
   */
  static async getUserInviteCode(userId) {
    try {
      const user = await User.findByPk(userId)
      if (!user) {
        throw new Error('用户不存在')
      }

      // 如果用户已有邀请码，直接返回
      if (user.invitation_code) {
        return user.invitation_code
      }

      // 生成新的邀请码
      let inviteCode
      let attempts = 0
      const maxAttempts = 10

      do {
        inviteCode = this.generateInviteCode(userId)
        const existingUser = await User.findOne({
          where: { invitation_code: inviteCode }
        })
        
        if (!existingUser) {
          break
        }
        
        attempts++
      } while (attempts < maxAttempts)

      if (attempts >= maxAttempts) {
        throw new Error('生成邀请码失败，请重试')
      }

      // 更新用户邀请码
      await user.update({ invitation_code: inviteCode })
      
      logger.info(`用户 ${userId} 生成邀请码: ${inviteCode}`)
      return inviteCode
    } catch (error) {
      logger.error('获取用户邀请码失败:', error)
      throw error
    }
  }

  /**
   * 生成邀请二维码
   * @param {string} inviteCode - 邀请码
   * @param {string} baseUrl - 基础URL
   * @returns {Promise<string>} 二维码数据URL
   */
  static async generateInviteQRCode(inviteCode, baseUrl = 'https://your-domain.com') {
    try {
      const inviteUrl = `${baseUrl}/invite?code=${inviteCode}`
      const qrCodeDataUrl = await QRCode.toDataURL(inviteUrl, {
        width: 300,
        margin: 2,
        color: {
          dark: '#000000',
          light: '#FFFFFF'
        }
      })
      
      return qrCodeDataUrl
    } catch (error) {
      logger.error('生成邀请二维码失败:', error)
      throw new Error('生成二维码失败')
    }
  }

  /**
   * 获取邀请分享信息
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 分享信息
   */
  static async getInviteShareInfo(userId) {
    try {
      const user = await User.findByPk(userId)
      if (!user) {
        throw new Error('用户不存在')
      }

      const inviteCode = await this.getUserInviteCode(userId)
      const qrCodeDataUrl = await this.generateInviteQRCode(inviteCode)

      // 获取邀请统计
      const inviteStats = await this.getInviteStats(userId)
      
      // 获取分享统计
      const shareStats = await ShareStatisticsService.getUserShareStats(userId)
      
      // 获取推荐分享渠道
      const recommendedChannels = await ShareStatisticsService.getRecommendedChannels(userId)

      return {
        inviteCode,
        qrCodeDataUrl,
        shareUrl: `https://your-domain.com/invite?code=${inviteCode}`,
        shareTitle: '邀请好友，一起赚积分！',
        shareDesc: `我在使用这个超棒的打印服务，邀请你一起来体验！使用我的邀请码 ${inviteCode}，我们都能获得奖励积分哦！`,
        stats: inviteStats,
        shareStats,
        recommendedChannels
      }
    } catch (error) {
      logger.error('获取邀请分享信息失败:', error)
      throw error
    }
  }

  /**
   * 处理邀请注册
   * @param {string} inviteCode - 邀请码
   * @param {number} newUserId - 新用户ID
   * @param {Object} extraData - 额外数据（IP、User-Agent等）
   * @returns {Promise<Object>} 处理结果
   */
  static async handleInviteRegister(inviteCode, newUserId, extraData = {}) {
    try {
      if (!inviteCode) {
        return { success: false, message: '邀请码为空' }
      }

      // 查找邀请人
      const inviter = await User.findOne({
        where: { invitation_code: inviteCode }
      })

      if (!inviter) {
        return { success: false, message: '邀请码无效' }
      }

      if (inviter.id === newUserId) {
        return { success: false, message: '不能邀请自己' }
      }

      // 检查是否已经被邀请过
      const existingInvitation = await Invitation.findOne({
        where: { invitee_id: newUserId }
      })

      if (existingInvitation) {
        return { success: false, message: '该用户已被邀请过' }
      }

      // 防刷检查
      const inviteData = {
        inviterId: inviter.id,
        inviteeId: newUserId,
        inviteCode,
        ipAddress: extraData.ipAddress,
        userAgent: extraData.userAgent,
        deviceId: extraData.deviceId
      }

      const riskResult = await InviteAntiCheatService.checkInviteCheat(inviteData)
      
      // 处理风险邀请
      if (riskResult.isRisk) {
        const riskHandleResult = await InviteAntiCheatService.handleRiskInvite(riskResult, inviteData)
        
        if (!riskHandleResult.success) {
          return riskHandleResult
        }
        
        if (riskHandleResult.needReview) {
          // 记录注册转化（即使需要审核）
          await ShareStatisticsService.recordRegisterConversion(
            inviteCode, 
            extraData.shareChannel, 
            extraData.sharePlatform
          )
          
          return {
            success: true,
            message: '邀请已提交审核，奖励将在审核通过后发放',
            invitation: riskHandleResult.invitation,
            needReview: true
          }
        }
      }

      // 创建邀请关系
      const invitation = await Invitation.create({
        inviter_id: inviter.id,
        invitee_id: newUserId,
        invite_code: inviteCode,
        register_time: new Date(),
        risk_data: riskResult.isRisk ? JSON.stringify(riskResult) : null
      })

      // 发放注册奖励
      await this.grantRegisterReward(inviter.id, newUserId)

      // 记录注册转化
      await ShareStatisticsService.recordRegisterConversion(
        inviteCode, 
        extraData.shareChannel, 
        extraData.sharePlatform
      )

      logger.info(`邀请注册成功: 邀请人 ${inviter.id}, 被邀请人 ${newUserId}`)

      return {
        success: true,
        message: '邀请注册成功',
        invitation
      }
    } catch (error) {
      logger.error('处理邀请注册失败:', error)
      throw error
    }
  }

  /**
   * 发放注册奖励
   * @param {number} inviterId - 邀请人ID
   * @param {number} inviteeId - 被邀请人ID
   */
  static async grantRegisterReward(inviterId, inviteeId) {
    try {
      // 获取动态奖励配置
      const rewardConfig = await this.getRewardConfig(inviterId)
      
      const registerReward = rewardConfig.registerReward
      const inviteReward = rewardConfig.inviteReward

      // 使用 PointsService 来发放奖励
      const pointsService = require('./pointsService')
      
      // 给被邀请人发放注册奖励
      await pointsService.addPoints(
        inviteeId,
        registerReward,
        'invite_register',
        '邀请注册奖励'
      )

      // 给邀请人发放邀请奖励
      await pointsService.addPoints(
        inviterId,
        inviteReward,
        'invite_register',
        '邀请好友注册奖励'
      )

      // PointsService 已经处理了用户积分更新，这里不需要重复更新

      // 更新邀请关系的奖励积分
      await Invitation.update(
        { total_reward_points: inviteReward },
        { where: { inviter_id: inviterId, invitee_id: inviteeId } }
      )

      // 检查是否达成邀请里程碑
      await this.checkInviteMilestone(inviterId)

      logger.info(`发放邀请奖励: 邀请人 ${inviterId} 获得 ${inviteReward} 积分, 被邀请人 ${inviteeId} 获得 ${registerReward} 积分`)
    } catch (error) {
      logger.error('发放注册奖励失败:', error)
      throw error
    }
  }

  /**
   * 获取奖励配置
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 奖励配置
   */
  static async getRewardConfig(userId) {
    try {
      // 获取用户等级和邀请统计
      const user = await User.findByPk(userId)
      const inviteCount = await Invitation.count({
        where: { inviter_id: userId, status: 1 }
      })

      // 基础奖励
      let registerReward = 50
      let inviteReward = 100

      // 根据用户等级调整奖励
      const levelMultiplier = this.getLevelMultiplier(user.memberLevel)
      
      // 根据邀请数量调整奖励
      const inviteMultiplier = this.getInviteMultiplier(inviteCount)

      registerReward = Math.floor(registerReward * levelMultiplier)
      inviteReward = Math.floor(inviteReward * levelMultiplier * inviteMultiplier)

      return {
        registerReward,
        inviteReward,
        levelMultiplier,
        inviteMultiplier
      }
    } catch (error) {
      logger.error('获取奖励配置失败:', error)
      // 返回默认配置
      return {
        registerReward: 50,
        inviteReward: 100,
        levelMultiplier: 1,
        inviteMultiplier: 1
      }
    }
  }

  /**
   * 获取等级倍数
   * @param {string} memberLevel - 会员等级
   * @returns {number} 倍数
   */
  static getLevelMultiplier(memberLevel) {
    const multipliers = {
      bronze: 1,
      silver: 1.2,
      gold: 1.5,
      platinum: 2,
      diamond: 2.5
    }
    return multipliers[memberLevel] || 1
  }

  /**
   * 获取邀请数量倍数
   * @param {number} inviteCount - 邀请数量
   * @returns {number} 倍数
   */
  static getInviteMultiplier(inviteCount) {
    if (inviteCount >= 100) return 1.5
    if (inviteCount >= 50) return 1.3
    if (inviteCount >= 20) return 1.2
    if (inviteCount >= 10) return 1.1
    return 1
  }

  /**
   * 检查邀请里程碑
   * @param {number} userId - 用户ID
   */
  static async checkInviteMilestone(userId) {
    try {
      const inviteCount = await Invitation.count({
        where: { inviter_id: userId, status: 1 }
      })

      const milestones = [
        { count: 1, reward: 50, title: '首次邀请' },
        { count: 5, reward: 200, title: '邀请达人' },
        { count: 10, reward: 500, title: '邀请专家' },
        { count: 20, reward: 1000, title: '邀请大师' },
        { count: 50, reward: 2500, title: '邀请王者' },
        { count: 100, reward: 5000, title: '邀请传说' }
      ]

      for (const milestone of milestones) {
        if (inviteCount === milestone.count) {
          // 发放里程碑奖励
          const pointsService = require('./pointsService')
          await pointsService.addPoints(
            userId,
            milestone.reward,
            'activity',
            `邀请里程碑奖励：${milestone.title}`
          )

          logger.info(`用户 ${userId} 达成邀请里程碑: ${milestone.title}, 获得 ${milestone.reward} 积分`)
          break
        }
      }
    } catch (error) {
      logger.error('检查邀请里程碑失败:', error)
    }
  }

  /**
   * 处理首次消费奖励
   * @param {number} userId - 用户ID
   * @param {number} amount - 消费金额
   */
  static async handleFirstConsumeReward(userId, amount) {
    try {
      // 查找邀请关系
      const invitation = await Invitation.findOne({
        where: { invitee_id: userId, status: 1 }
      })

      if (!invitation || invitation.first_consume_time) {
        return // 没有邀请关系或已经发放过首次消费奖励
      }

      // 更新首次消费时间
      await invitation.update({
        first_consume_time: new Date()
      })

      // 计算奖励积分（消费金额的10%）
      const rewardPoints = Math.floor(amount * 0.1)
      
      if (rewardPoints > 0) {
        // 给邀请人发放奖励
        const pointsService = require('./pointsService')
        await pointsService.addPoints(
          invitation.inviter_id,
          rewardPoints,
          'invite_consume',
          `邀请好友首次消费奖励`
        )

        // 更新总奖励积分
        await invitation.update({
          total_reward_points: invitation.total_reward_points + rewardPoints
        })

        logger.info(`发放首次消费奖励: 邀请人 ${invitation.inviter_id} 获得 ${rewardPoints} 积分`)
      }
    } catch (error) {
      logger.error('处理首次消费奖励失败:', error)
    }
  }

  /**
   * 获取邀请统计
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 邀请统计
   */
  static async getInviteStats(userId) {
    try {
      const invitations = await Invitation.findAll({
        where: { inviter_id: userId, status: 1 },
        include: [{
          model: User,
          as: 'invitee',
          attributes: ['id', 'nickname', 'avatar', 'created_at']
        }]
      })

      const totalInvites = invitations.length
      const totalRewards = invitations.reduce((sum, inv) => sum + parseFloat(inv.total_reward_points), 0)
      const firstConsumeCount = invitations.filter(inv => inv.first_consume_time).length
      
      // 本月邀请数
      const thisMonth = new Date()
      thisMonth.setDate(1)
      thisMonth.setHours(0, 0, 0, 0)
      
      const monthlyInvites = invitations.filter(inv => 
        new Date(inv.register_time) >= thisMonth
      ).length

      return {
        totalInvites,
        totalRewards,
        firstConsumeCount,
        monthlyInvites,
        completionRate: totalInvites > 0 ? Math.round((firstConsumeCount / totalInvites) * 100) : 0,
        recentInvites: invitations.slice(0, 10).map(inv => ({
          id: inv.id,
          invitee: inv.invitee,
          registerTime: inv.register_time,
          firstConsumeTime: inv.first_consume_time,
          rewardPoints: parseFloat(inv.total_reward_points)
        }))
      }
    } catch (error) {
      logger.error('获取邀请统计失败:', error)
      throw error
    }
  }

  /**
   * 获取邀请排行榜
   * @param {Object} options - 选项
   * @returns {Promise<Array>} 排行榜数据
   */
  static async getInviteRanking(options = {}) {
    try {
      const {
        limit = 50,
        period = 'all', // all, month, week
        type = 'count' // count, rewards
      } = options

      let whereClause = { status: 1 }
      
      const { Op } = require('sequelize')
      
      // 时间筛选
      if (period === 'month') {
        const startOfMonth = new Date()
        startOfMonth.setDate(1)
        startOfMonth.setHours(0, 0, 0, 0)
        whereClause.register_time = { [Op.gte]: startOfMonth }
      } else if (period === 'week') {
        const startOfWeek = new Date()
        startOfWeek.setDate(startOfWeek.getDate() - startOfWeek.getDay())
        startOfWeek.setHours(0, 0, 0, 0)
        whereClause.register_time = { [Op.gte]: startOfWeek }
      }
      const sequelize = require('../config/database')

      let orderBy = type === 'rewards' ? 
        [[sequelize.fn('SUM', sequelize.col('Invitation.total_reward_points')), 'DESC']] :
        [[sequelize.fn('COUNT', sequelize.col('Invitation.id')), 'DESC']]

      const rankings = await Invitation.findAll({
        where: whereClause,
        attributes: [
          'inviter_id',
          [sequelize.fn('COUNT', sequelize.col('Invitation.id')), 'invite_count'],
          [sequelize.fn('SUM', sequelize.col('Invitation.total_reward_points')), 'total_rewards']
        ],
        include: [{
          model: User,
          as: 'inviter',
          attributes: ['id', 'nickname', 'avatar']
        }],
        group: ['Invitation.inviter_id', 'inviter.id'],
        order: orderBy,
        limit
      })

      return rankings.map((item, index) => ({
        rank: index + 1,
        user: item.inviter,
        inviteCount: parseInt(item.getDataValue('invite_count')),
        totalRewards: parseFloat(item.getDataValue('total_rewards') || 0)
      }))
    } catch (error) {
      logger.error('获取邀请排行榜失败:', error)
      throw error
    }
  }

  /**
   * 获取邀请详情列表
   * @param {number} userId - 用户ID
   * @param {Object} options - 选项
   * @returns {Promise<Object>} 邀请详情
   */
  static async getInviteDetails(userId, options = {}) {
    try {
      const {
        page = 1,
        limit = 20,
        status = 'all' // all, completed, pending
      } = options

      let whereClause = { inviter_id: userId, status: 1 }
      
      const { Op } = require('sequelize')
      
      if (status === 'completed') {
        whereClause.first_consume_time = { [Op.ne]: null }
      } else if (status === 'pending') {
        whereClause.first_consume_time = null
      }
      const offset = (page - 1) * limit

      const { count, rows } = await Invitation.findAndCountAll({
        where: whereClause,
        include: [{
          model: User,
          as: 'invitee',
          attributes: ['id', 'nickname', 'avatar', 'created_at']
        }],
        order: [['created_at', 'DESC']],
        limit,
        offset
      })

      const invitations = rows.map(inv => ({
        id: inv.id,
        invitee: inv.invitee,
        registerTime: inv.register_time,
        firstConsumeTime: inv.first_consume_time,
        rewardPoints: parseFloat(inv.total_reward_points),
        status: inv.first_consume_time ? 'completed' : 'pending'
      }))

      return {
        total: count,
        page,
        limit,
        totalPages: Math.ceil(count / limit),
        invitations
      }
    } catch (error) {
      logger.error('获取邀请详情失败:', error)
      throw error
    }
  }
}

module.exports = InvitationService